﻿package com.feib.ebilling.job;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.enterprisedt.net.ftp.FTPFile;
import com.enterprisedt.net.ftp.FileTransferClient;
import com.feib.ebilling.job.dao.BankingFeedbackDao;
import com.feib.ebilling.job.service.FtpService;
import com.feib.ebilling.job.util.StringUtils;

/**
 * @title (#)WrittenOffFeedback.java<br>
 * @description 中租車貸策略聯盟銷帳資料回饋檔TYPAY<br>
 * @author Fiona Huang<br>
 * @version 1.0.0 2011/11/09
 * @version 1.0.1 2012/10/15
 * @copyright Far Eastern International Bank Copyright (c) 2011<br>
 * @2011/11/09 create by Fiona Huang<br>
 * @2012/10/15 modified by Monica Tan For 中租迪和拆分為中租+合迪（N-201210248）<br>
 * @remark 每個月營業日的第一日，會依據優利產出的TYPAY月檔一併產出TYPAY+FINTYPAY月檔
 * @remark 沒有可以輸入參數日期的用意就是為了上面原因，Fiona偷懶不想判斷日期，有.TXT結尾的TYPAY檔都吃
 * @remark 吃進TYPAY的TXT檔，執行過後該檔更名為.bak
 * @remark 一定要在BankingFeedbackBussinessDate.bat之後執行，限中租使用<br>
 */

@Service("writtenOffFeedback")
public class WrittenOffFeedback {
	public static Logger logger = LoggerFactory
			.getLogger(WrittenOffFeedback.class);

	/* 中租車貸策略聯絡的代號 */
	private static final String CHAILEASE = "865170966930";

	/* 合迪車貸策略聯絡的代號 */
	private static final String FINATRADE = "865170966990";

	/* 輸入參數的業者代號 */
	private static String groupNo;

	/* 輸入參數的業者名稱 */
	private static String groupName;

	/* 最終產出檔名標題 */
	private static String resultFileTitle;

	/* 供比對虛擬帳號開頭三碼形式 693 or 699*/
	private static String accountType;

	/* 判斷為最後一個傳入參數業者時，將FEIB FTP內的TYPAY.TXT 更名為.bak */
	private static String finalGroup;

	public static final SimpleDateFormat BASIC_DATE_TIME_FORMAT = new SimpleDateFormat(
			"yyyy/MM/dd HH:mm:ss");

	@Resource(name = "ftpService")
	private FtpService ftpService;

	@Resource(name = "ftpProperties")
	private Properties ftpProperties;

	public static Map<String, String> CHANEL_CODE = new HashMap<String, String>();
	static {
		CHANEL_CODE.put("7111111", "1");
		CHANEL_CODE.put("TFM", "2");
		CHANEL_CODE.put("HILIFE", "3");
		CHANEL_CODE.put("OKCVS", "4");
		CHANEL_CODE.put("POST", "5");
	}

	@Resource(name = "bankingFeedbackDao")
	private BankingFeedbackDao bankingFeedbackDao;

	public static void main(String[] args) {

		ApplicationContext ctx = new ClassPathXmlApplicationContext(
				new String[] { "applicationContext-config.xml",
						"applicationContext-dao.xml",
						"applicationContext-properties.xml" });

		Date start = new Date();

		if (null == args || 0 == args.length) {
			System.out.println("WrittenOffFeedback [中租+合迪車貸策略聯盟銷帳資料回饋檔TYPAY]");
			logger.info("WrittenOffFeedback： [沒有傳入業者代號]");
			return; // 結束main()
		} else {
			finalGroup = args[args.length - 1];
		}

		for (String gNo : args) {
			groupNo = gNo;

			if (groupNo.equals(CHAILEASE)) {
				groupName = "中租";
				resultFileTitle = "TYPAY";
				accountType = "693";
			} else if (groupNo.equals(FINATRADE)) {
				groupName = "合迪";
				resultFileTitle = "FINTYPAY";
				accountType = "699";
			} else {
				System.out.println("WrittenOffFeedback [不知名的業者代號-執行結束]");
				logger.info("WrittenOffFeedback [不知名的業者代號-執行結束]");
				return; // 結束main()
			}

			logger.info("[開始] {}車貸策略聯盟銷帳資料回饋檔  - {}", groupName,
					BASIC_DATE_TIME_FORMAT.format(start));
			try {
				WrittenOffFeedback writtenOffFeedback = (WrittenOffFeedback) ctx
						.getBean("writtenOffFeedback");
				writtenOffFeedback.getFiles("FEIB", "TYPAY");
			} catch (Exception e) {
				logger.error("[錯誤]" + e.getMessage(), e);
			} finally {
				Date end = new Date();
				logger.info("[結束] {}車貸策略聯盟銷帳資料回饋檔 - {}", groupName,
						BASIC_DATE_TIME_FORMAT.format(start));
				logger.info("共費時 - "
						+ ((end.getTime() - start.getTime()) / 1000) + " 秒");
			}
		}
	}

	public void getFiles(String sChanel, String FileName) {
		FileTransferClient ftp = null;
		/* 取得FTP設定 */
		String host = ftpProperties.getProperty(sChanel + "#FTPServerIP");
		String username = ftpProperties.getProperty(sChanel + "#FTPUserName");
		String password = ftpProperties.getProperty(sChanel + "#FTPPassword");
		String localFolder = ftpProperties
				.getProperty(sChanel + "#LocalFolder");
		String remoteFolder = ftpProperties.getProperty(sChanel
				+ "#RemoteFolder");

		logger.info("FTP Server Connect : {}", host);
		logger.info("FTP User Name : {}", username);
		logger.info("FTP Local Directory : {}", localFolder);
		logger.info("FTP Remote Directory : {}", remoteFolder);

		try {
			ftp = new FileTransferClient();
			ftp.setRemoteHost(host);
			ftp.setUserName(username);
			ftp.setPassword(password);
			ftp.connect();
			if (ftp.isConnected()) {

				/* 切換FTP目錄 */
				if (remoteFolder != null && !remoteFolder.trim().equals("")) {
					ftp.changeDirectory(remoteFolder);
					logger.info("Directory change to {}",
							ftp.getRemoteDirectory());
				}

				/* 列出Server上的檔案 */
				FTPFile[] ftpFiles = ftp.directoryList();
				String sFileName = null;
				for (FTPFile ftpFile : ftpFiles) {
					if (ftpFile.isDir()) {
						logger.info("{} is directory. skip", ftpFile.getName());
						continue;
					} else if (ftpFile.isLink()) {
						logger.info("{} is Link. skip", ftpFile.getName());
						continue;
					} else {
						/* 讀取檔案 */
						sFileName = ftpFile.getName().toUpperCase();
						/* 過濾檔名前五位是 TYPAY */
						if (!FileName.equals(sFileName.substring(0, 5)))
							continue;
						/* 副檔名是.TXT */
						if (!sFileName.substring(sFileName.length() - 4,
								sFileName.length()).equals(".TXT"))
							continue;
						/* 下載檔案 */
						logger.info("File {} size is {} Bytes", sFileName,
								ftp.getSize(sFileName));
						ftp.downloadFile(localFolder, sFileName);
						logger.info("{} is download", sFileName);

						/*
						 * 獲取檔名日期拼裝 =>TYPAY+_YYYYMMDD.TXT or
						 * FINTYPAY_YYYYMMDD.TXT
						 */
						String sFinalFileName = null; 
						sFinalFileName = resultFileTitle + sFileName.substring(5);
						//System.out.println("sFileName:"+sFileName);
						//System.out.println("sFinalFileName:"+sFinalFileName);

						/* 開啟檔案 */
						File uploadedFile = new File(localFolder + "\\"
								+ sFileName);
						StringBuffer sbf = new StringBuffer();
						long total = 0;

						if (uploadedFile.exists()) {
							String str = null;
							String channel = "";
							String userno = "";
							FileInputStream fileInputStream = new FileInputStream(
									uploadedFile);
							BufferedReader reader = new BufferedReader(
									new InputStreamReader(fileInputStream,
											"Big5"));
							while ((str = reader.readLine()) != null) {
								if (str.length() > 0) {
									// 處理讀取BOM(byte-order
									// mark)格式檔案,在讀取utf8檔案的開頭會有utf8檔案格式的標記,需略過此標記再重串內容,標記16進位EF
									// BB BF
									int c = str.charAt(0);
									if (c == 65279) {
										str = str.substring(1, str.length());
									}
								}
								userno = StringUtils.DBCSsubstring(str, 223,
										239);

								/* 區分該寫入中租(693) or 合迪(699) */
								if (accountType.equals(userno.substring(0, 3))) {
									/* 檔案有中文需特殊處理 */
									// 截掉最後的1碼channel(下面會撈資料庫的通路補上此碼)
									// 和16碼虛擬帳號(因回給業者的銷帳檔不需此資訊)
									sbf.append(str.substring(0,	str.length() - 17));
									if (StringUtils
											.DBCSsubstring(str, 222, 223)
											.equals("0")) {
										/* 優利預設帶0，由eBilling判斷是否為超商、郵局通路代碼 */
										channel = getChannel(userno);

										if (channel.equals("")) {
											/* 銀行通路 */
											sbf.append("0");
											channel = "0";
										} else {
											/* 超商、郵局通路 */
											sbf.append(channel);

											/* 中租補資料用 */
											StringBuffer sbfTemp = new StringBuffer();
											/* 扣款日 */
											sbfTemp.append(StringUtils
													.DBCSsubstring(str, 197,
															205)
													+ "\t");
											/* 繳費帳號 */
											sbfTemp.append(StringUtils
													.DBCSsubstring(str, 223,
															239)
													+ "\t");
											/* 客戶編號 */
											sbfTemp.append(StringUtils
													.DBCSsubstring(str, 103,
															119)
													+ "\t");
											/* 客戶名稱 */
											sbfTemp.append(StringUtils
													.DBCSsubstring(str, 35, 103)
													+ "\t");
											/* 繳費金額 */
											int iTemp = Integer
													.parseInt(StringUtils
															.DBCSsubstring(str,
																	135, 143))
													+ Integer
															.parseInt(StringUtils
																	.DBCSsubstring(
																			str,
																			143,
																			151));
											sbfTemp.append(String
													.valueOf(iTemp) + "\t");
											/* 繳款通路 */
											if (channel.equals("1")) {
												sbfTemp.append("統一超商\t");
											} else if (channel.equals("2")) {
												sbfTemp.append("全家超商\t");
											} else if (channel.equals("3")) {
												sbfTemp.append("萊爾富超商\t");
											} else if (channel.equals("4")) {
												sbfTemp.append("ＯＫ超商\t");
											} else if (channel.equals("5")) {
												sbfTemp.append("郵局超商\t");
											}
											// logger.info("{}",sbfTemp.toString());
										}
									} else {
										/* 優利有回饋通路代碼 */
										sbf.append(StringUtils.DBCSsubstring(
												str, 222, 223));
									}
									sbf.append("\r\n");
									logger.info("虛擬帳號:{}, 繳款管道:{}", userno, channel);
									total++;
								}
							}
						}
						logger.info("{}車貸策略聯盟銷帳資料筆數:{}", groupName, total);
						/* 轉上傳至中租FTP Sever */
						ftpService.putFTPFile(groupNo, "", sbf.toString(),
								sFinalFileName);
						logger.info("{} is upload", sFinalFileName);

						/* 20120424增加ZIP加密檔案 */
						ftpService.zipFTPFile(groupNo, sFinalFileName);
						logger.info(
								"{} is zip password protect",
								sFinalFileName.substring(0,
										sFinalFileName.length() - 4)
										+ ".zip");
						
						/* 確認為最後一個參數才做檔名變更 */
						if (groupNo.equals(finalGroup)) {
							/* 處理過的檔案修改檔名-FTP端 */
							ftp.rename(
									sFileName,
										sFileName.substring(0,
											sFileName.length()-4)
											+ ".bak");
							/* 異動檔案名稱 */
							logger.info(
									"{} is rename",
									sFileName.substring(0,
											sFileName.length()-4)
											+ ".bak");
						}
					}
				}
			}
		} catch (Exception ex) {
			logger.error("[錯誤]" + ex.toString(), ex);
		} finally {
			if (null != ftp)
				try {
					ftp.disconnect(true);
				} catch (Exception ex) {
					logger.error("[錯誤]" + ex.toString(), ex);
				}
		}
	}

	@Transactional(readOnly = false)
	public String getChannel(String userno) {
		// 取得 DB Connection
		Connection con = DataSourceUtils.getConnection(bankingFeedbackDao
				.getDataSource());
		Statement stmt = null;
		String channel = "";
		try {
			stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
			String sql = "select * from FEEDBACK_LOG where USERNO = '" + userno
					+ "' ";
			ResultSet rs = null;
			try {
				rs = stmt.executeQuery(sql);
				if (rs.next()) {
					channel = CHANEL_CODE.get(rs.getString("CHANNEL"));
				} else {
					channel = "";
				}
			} finally {
				JdbcUtils.closeResultSet(rs);
			}
			return channel;
		} catch (Exception e) {
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con,
					bankingFeedbackDao.getDataSource());
			con = null;
			throw new RuntimeException(e);
		} finally {
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con,
					bankingFeedbackDao.getDataSource());
			con = null;
		}
	}
}
